﻿#include "ttucmd.h"

TTucmd::TTucmd(int devtype,int index,const QString &user,const QString &key):
    mDeviceType(devtype),
    mDevIndex(index),
    mUser(user),
    mKey(key)
{
    mpTimer = new QTimer();
    if(mpTimer==nullptr){
        qout << g_C2Q("new mSerial failed");
        return;
    }
    connect(mpTimer,SIGNAL(timeout()),this,SLOT(HandleTimeout()));

    mSerial = new QSerialPort();
    if(mSerial==nullptr){
        qout << g_C2Q("new mSerial failed");
        return;
    }
    connect(mSerial,SIGNAL(readyRead()),this,SLOT(readData()));

    RevData.clear();
    mRevOKFlag=false;
    miSteps=0;
    isFuseTermMap=false;

    if(mDeviceType==0){
        mTotalSteps = 11;
    }
    else if(mDeviceType == 1){
        mTotalSteps = 12;
    }
    else{
        qerr << "error Device type :" << mDeviceType;
        mTotalSteps = 0;
    }

    mLastSendCmd = "";

    m_bConnected = false;
    m_pSshSocket = nullptr;
}

TTucmd::~TTucmd()
{
    if(m_pSshSocket!=nullptr){
        m_pSshSocket->disconnectFromHost();
        m_pSshSocket = nullptr;
    }
}

void TTucmd::setSerialArgs(QString portname, unsigned int baudrate, int parity, int databits, int stopbits)
{
    mPortArgs.PortName = portname;
    mPortArgs.BaudRate = baudrate;
    mPortArgs.Parity = parity;
    mPortArgs.DataBits = databits;
    mPortArgs.StopBits = stopbits;
}

void TTucmd::setSerialArgs(QString ip, int port)
{
    mPortArgs.IP = ip;
    mPortArgs.port = port;

    mPortArgs.StrIpPort = ip+":" + QString::number(port);

    initParams();
}

bool TTucmd::openPort(int flag)
{
    linkModel = flag;
    if(flag==0){
        if(m_bConnected)
            return false;
        if(m_pSshSocket == nullptr){
            m_pSshSocket = new QSsh::SshConnection(m_argParameters);
            connect(m_pSshSocket,SIGNAL(connected()),SLOT(slotConnected()));
            connect(m_pSshSocket,SIGNAL(error(QSsh::SshError)),SLOT(slotSshConnectError(QSsh::SshError)));
        }
        m_pSshSocket->connectToHost();
    }
    else{
        if(!mSerial->isOpen()){
            mSerial->setPortName(mPortArgs.PortName);
            if(!mSerial->open(QIODevice::ReadWrite)){
                qout << g_C2Q("串口打开失败:") << mPortArgs.PortName;
                return false;
            }
            if(!mSerial->setBaudRate(mPortArgs.BaudRate)){
                qout << g_C2Q("串口波特率设置失败:")<<mPortArgs.BaudRate;
                return false;
            }

            bool ret=false;
            if(mPortArgs.DataBits == 5){
                ret = mSerial->setDataBits(QSerialPort::Data5);
            }
            else if(mPortArgs.DataBits == 6){
                ret = mSerial->setDataBits(QSerialPort::Data6);
            }
            else if(mPortArgs.DataBits == 7){
                ret = mSerial->setDataBits(QSerialPort::Data7);
            }
            else if(mPortArgs.DataBits == 8){
                ret = mSerial->setDataBits(QSerialPort::Data8);
            }
            if(!ret){
                qout << g_C2Q("串口数据位设置失败:")<<mPortArgs.BaudRate;
                return false;
            }

            if(mPortArgs.Parity == 0){
                ret = mSerial->setParity(QSerialPort::NoParity);
            }
            else if(mPortArgs.Parity == 1){
                ret = mSerial->setParity(QSerialPort::OddParity);
            }
            else if(mPortArgs.Parity == 2){
                ret = mSerial->setParity(QSerialPort::EvenParity);
            }
            else if(mPortArgs.Parity == 3){
                ret = mSerial->setParity(QSerialPort::SpaceParity);
            }
            else if(mPortArgs.Parity == 4){
                ret = mSerial->setParity(QSerialPort::MarkParity);
            }
            else
                return false;
            if(!ret){
                qout << g_C2Q("串口校验位设置失败:")<<mPortArgs.BaudRate;
                return false;
            }

            if(mPortArgs.StopBits == 0){
                ret = mSerial->setStopBits(QSerialPort::OneStop);
            }
            else if(mPortArgs.StopBits == 1){
                ret = mSerial->setStopBits(QSerialPort::OneAndHalfStop);
            }
            else if(mPortArgs.StopBits == 2){
                ret = mSerial->setStopBits(QSerialPort::TwoStop);
            }
            else{
                return false;
            }
            if(!ret){
                qout << g_C2Q("串口停止位设置失败:")<<mPortArgs.StopBits;
                return false;
            }

            if(!mSerial->setFlowControl(QSerialPort::NoFlowControl)){
                qout << g_C2Q("串口流控设置失败:")<<"QSerialPort::NoFlowControl";
                return false;
            }
            return true;
        }
        else{
            return false;
        }
    }
    return true;
}

void TTucmd::closePort(int flag)
{
    if(flag==0){
        if(m_pSshSocket!=nullptr){
            m_pSshSocket->disconnectFromHost();
            m_bConnected = false;
        }
    }
    else{
        if(mSerial!=nullptr && mSerial->isOpen()){
            mSerial->clear();
            mSerial->close();
        }
    }
}

void TTucmd::setTTUIP(QString ip)
{
    QString cmd= "ip addr add "+ip+"/24 dev FE0";
    if(!sendCmd(cmd)){
        qout << "setTTUIP error!";
    }
}

void TTucmd::getVersion()
{
    QString cmd = "version -b";
    if(!sendCmd(cmd)){
        qout << "getVersion error!";
    }
}

void TTucmd::getScuVersion()
{
    QString cmd = "devctl -H";
    if(!sendCmd(cmd)){
        qout << "getHardVersion error!";
    }
}

void TTucmd::getCPUInfo()
{
    QString cmd = "cat /proc/cpuinfo";
    if(!sendCmd(cmd)){
        qout << "getCPUInfo error!";
    }
}

void TTucmd::checkOnline()
{
    QString cmd = "ping 8.8.8.8";
    if(!sendCmd(cmd)){
        qout << "checkOnline error!";
    }
}

void TTucmd::getContainerSts()
{
    QString cmd = "container status";
    if(!sendCmd(cmd)){
        qout << "getContainerSts error!";
    }
}

void TTucmd::stopContainer(QString name)
{
    QString cmd = "container stop "+name;
    if(mDeviceType==1)
    {
        cmd.insert(0,"sudo ");
    }
    if(!sendCmd(cmd)){
        qout << "stopContainer error!";
    }
}

void TTucmd::startContainer(QString name)
{
    QString cmd = "container start "+name;
    if(mDeviceType==1)
    {
        cmd.insert(0,"sudo ");
    }
    if(!sendCmd(cmd)){
        qout << "startContainer error!";
    }
}

void TTucmd::queryProcess()
{
    QString cmd = "top -b -n 1 -d 10";//sudo -s
    if(!sendCmd(cmd)){
        qout << "query process information!";
    }
}

void TTucmd::getAppInfo(QString contname)
{
    QString cmd = "appm -I -c "+contname;
    if(!sendCmd(cmd)){
        qout << "getAppInfo error!";
    }
}

void TTucmd::stopApp(QString contname, QString Appname)
{
    QString cmd = QString("appm -S -c %1 -n %2").arg(contname).arg(Appname);
    if(mDeviceType==1)
    {
        cmd.insert(0,"sudo ");
    }
    if(!sendCmd(cmd)){
        qout << "stopApp error!";
    }
}

void TTucmd::startApp(QString contname, QString Appname)
{
    QString cmd = QString("appm -s -c %1 -n %2").arg(contname).arg(Appname);
    if(mDeviceType==1)
    {
        cmd.insert(0,"sudo ");
    }
    if(!sendCmd(cmd)){
        qout << "startApp error!";
    }
}

void TTucmd::copyApp(QString frompath, QString topath)
{
    QString cmd = QString("curl ftp://%1 -o %2").arg(frompath).arg(topath);
    if(!sendCmd(cmd)){
        qout << "copyApp error!";
    }
}

void TTucmd::installApp(QString contname, QString apppath)
{
    QString cmd = QString("appm -i -c %1 -f %2").arg(contname).arg(apppath);
    if(!sendCmd(cmd)){
        qout << "installApp error!";
    }
}

void TTucmd::uninstallApp(QString contname, QString appname)
{
    QString cmd = QString("appm -u -c %1 -n %2").arg(contname).arg(appname);
    if(!sendCmd(cmd)){
        qout << "uninstallApp error!";
    }
}

void TTucmd::setIp(QString ip)
{
    mIp=ip;
}

void TTucmd::setStep(int step)
{
    if(step>4 || step<0){
        qout << "add netmapping step is out of range !";
        step=0;
    }
    miSteps=step;
}

void TTucmd::setNetMap(QString ip1, QString ip2)
{
    mNetMapIp1=ip1;
    mNetMapIp2=ip2;
}

void TTucmd::mapInterAcess()
{
    if(mDeviceType==0){ //华为ttu
        if(miSteps==5&&mRoleIndex<mRoleTable.length()&&mRoleIndex!=0){  //删除规则表
            --miSteps;
        }

        if(miSteps==2&&mOldIpList.length()>0){      //删除原有网口
            --miSteps;
        }

        switch (miSteps) {
        case 0:
            getAllIp();
            break;
        case 1:
            if(mOldIpList.length()>0){
                delOldIP(mOldIpList.at(0));
            }
            else{
                mRevOKFlag=true;        //原来没有则直接进行下一步
            }
            break;
        case 2:
            setTTUIP(mIp);
            break;
        case 3:
            QueryRuleTable();
            break;
        case 4:
            if(mRoleIndex<mRoleTable.length()){
                DelRuleTable(mRoleTable.value(mRoleIndex));
                ++mRoleIndex;
            }
            break;
        case 5:
            addRuleTable();
            break;
        case 6:
            addChain("nft add chain dnat1 prerouting { type nat hook prerouting priority 0 \\; }");
            break;
        case 7:
            addChain("nft add chain dnat1 postrouting { type nat hook postrouting priority 100 \\; }");
            break;
        case 8:
            addNetMapping();
            break;
        case 9:
            rebootDev();
            break;
        case 10:
            confirmRebootDev();
            break;

        default:
            return;
        }
    }
    else if(mDeviceType ==1){
        isFuseTermMap= true;
        mRevOKFlag=true;        //只能融合终端需要操作vim，直接默认回复
        switch (miSteps) {
        case 1://开始ip设置
            openFile("/etc/network/interfaces.d/FE0");
            break;
        case 2:
            sendCmd("\r","");
            break;
        case 3:
            FindText("/address");
            break;
        case 4:
            deletLine();
            break;
        case 5:
            EditBeforeLine();
            break;
        case 6:
            insertText(mIp);
            break;
        case 7:
            sendCmd(QChar(0x1b),"");
            break;
        case 8:
            SaveExitVim();
            break;
        case 9://开始开启ssh服务
            openFile("/etc/rc.local");
            break;
        case 10:
            startSSH();
            break;
        case 11:
            SaveExitVim();
            break;
        case 12:    //只能融合终端直接重启，不再询问
            rebootDev();
            break;
        default:
            return;
        }
    }
    mpTimer->start(WAITTIME);
    ++miSteps;
}

void TTucmd::SetAuthority(QString PermissionLevel, QString FileName)
{
    QString cmd = QString("sudo chmod ") + PermissionLevel + " " + FileName;
    if (!sendCmd(cmd)) {
        qout << "SetAuthority error!";
    }
}

void TTucmd::StartExeProgram(QString ExePath)
{
    QString cmd = QString("sudo ") + ExePath;
    if (!sendCmd(cmd)) {
        qout << "StartExeProgram error!";
    }
}

void TTucmd::SetCombinationKeys(QString Keys)
{
    QString cmd = Keys;
    if (!sendCmd(cmd)) {
        qout << "SetCombinationKeys error!";
    }
}

void TTucmd::RestartContainer(QString ContainerName)
{
    QString cmd = QString("sudo container restart ") + ContainerName;
    if (!sendCmd(cmd)) {
        qout << "RestartContainer error!";
    }
}

void TTucmd::getESN()
{
    QString cmd = QString("devctl -e");
    if (!sendCmd(cmd)) {
        qout << "devctl -e error!" << cmd;
    }
}

void TTucmd::getSysVersion()
{
    QString cmd = QString("version -d");
    if (!sendCmd(cmd)) {
        qout << "get system version error!" << cmd;
    }
}

void TTucmd::getAllIp()
{
    QString cmd = QString("ip addr show");
    if(!sendCmd(cmd)){
        qout << "getAllIp error!";
    }
}

void TTucmd::delOldIP(QString ip)
{
    QString cmd = QString("ip addr del ")+ip+(" dev FE0");
    if(!sendCmd(cmd)){
        qout << "delOldIP error!";
    }
}

void TTucmd::rebootDev()
{
    QString cmd = QString("reboot -f");
    if(!((mDeviceType==1)?sendSudoCmd(cmd,"\r"):sendCmd(cmd,"\r"))){
        qout << "rebootDev error!";
    }
}

void TTucmd::getAppVersion(QString contain,QString app)
{
    QString cmd = QString("appm -I -c %1 -n %2").arg(contain).arg(app);
    if(mDeviceType==1)
    {
        cmd.insert(0,"sudo ");
    }
    if(!sendCmd(cmd)){
        qout << "getAppVersion error!";
    }
}

void TTucmd::writeUserName()
{
    if(!sendCmd(mUser,"\r")){
        qout << "writeUserName error!";
    }
}

void TTucmd::writePassword()
{
    if(!sendCmd(mKey,"\r")){
        qout << "writePassword error!";
    }
}

void TTucmd::changUsr(int usr)
{
    QString cmd="";
    switch (usr) {
    case 0:
        cmd = "exit";
        break;
    case 1:
        cmd = "sudo -s";
        break;
    default:
        qerr << "illegal user id";
        break;
    }
    if(!sendCmd(cmd,"\r")){
        qerr << g_C2Q("切换用户命令发送失败");
    }
}

void TTucmd::FindText(const QString &text)
{
    if(!sendCmd(text,"\r")){
        qerr << g_C2Q("查找字段失败") << text;
    }
}

void TTucmd::deletLine()
{
    if(!sendCmd("dd","")){
        qerr << g_C2Q("删除行失败");
    }
}

void TTucmd::EditBeforeLine()
{
    if(!sendCmd("O","")){
        qerr << g_C2Q("向前插入一行失败");
    }
}

void TTucmd::insertText(const QString &text)
{
    QString ip = "address" + text;
    if(!sendCmd(ip,"\r")){
        qerr << g_C2Q("插入失败") << text;
    }
}

void TTucmd::openFile(const QString &name)
{
    QString vi = "vi ";
    vi+=name;
    if(!sendCmd(vi,"\r")){
        qerr << g_C2Q("打开文件命令发送失败");
    }
}

void TTucmd::startSSH()
{
    if(!sendCmd(":%s /#systemctl/systemctl","\r")){
        qerr << g_C2Q("开启ssh服务命令发送失败");
    }
}

void TTucmd::GpsTime()
{
    QString cmd = QString("sudo bd -G -t");
    if(!sendCmd(cmd)){
        qout << "GpsTime error!";
    }
}

void TTucmd::BdTime()
{
    QString cmd = QString("sudo bd -B -t");
    if(!sendCmd(cmd)){
        qout << "BdTime error!";
    }
}

void TTucmd::GPSAndBdTime()
{
    QString cmd = QString("sudo bd -G_B -t");
    if(!sendCmd(cmd)){
        qout << "GPSAndBdTime error!";
    }
}

void TTucmd::GpsPos()
{
    QString cmd = QString("sudo bd -G -l");
    if(!sendCmd(cmd)){
        qout << "GpsPos error!";
    }
}

void TTucmd::BdPos()
{
    QString cmd = QString("sudo bd -B -l");
    if(!sendCmd(cmd)){
        qout << "BdPos error!";
    }
}

void TTucmd::GPSAndBdPos()
{
    QString cmd = QString("sudo bd -G_B -l");
    if(!sendCmd(cmd)){
        qout << "GPSAndBdPos error!";
    }
}

void TTucmd::confirmRebootDev()
{
    QString cmd = QString("y\r");     //为y\n所以不能用通用方式
    RevData.clear();
    QByteArray tmpary(cmd.toLatin1());
    if(!tmpary.isEmpty()){
        int len = m_shell->write(tmpary);
        if(len!=tmpary.length()){
            qout << "write length error!write len "<<len<<"datalen " << tmpary.length();
        }
        emit SendCmdMsg(mDevIndex,cmd);
    }
}

bool TTucmd::sendCmd(QString cmd, QString endstr)
{
    if(!m_bConnected)
        return false;
    RevData.clear();
    cmd += endstr;
    if(!cmd.contains("sudo -s")&&!cmd.contains(mUser)&&!cmd.contains(mKey))
        mLastSendCmd = cmd;

    QByteArray tmpary = Str2Hex(cmd);
    if(!tmpary.isEmpty()){
        int len = linkModel==0?m_shell->write(tmpary):mSerial->write(tmpary);
        if(len!=tmpary.length()){
            qout << "write length error!write len "<<len<<"datalen " << tmpary.length();
            return false;
        }
        emit SendCmdMsg(mDevIndex,cmd);
        return true;
    }
    return false;
}

bool TTucmd::sendSudoCmd(QString cmd, QString endstr)
{
    return sendCmd("sudo "+cmd,endstr);
}

QString TTucmd::Hex2Str(QByteArray array)
{
     if(array.isEmpty()){
         return "";
     }
     QString text(array);
     if(array.contains("top -b -n 1 -d 10"))
     {
         if(text.length()>384){
             int end = array.lastIndexOf("\n");
             int begin =  array.indexOf("\n",384);
             text.remove(begin,end-begin);
         }
     }
     return text;
}

QByteArray TTucmd::Str2Hex(QString str)
{
    QByteArray array;
    array.clear();
    if(str.isEmpty()){
        return array;
    }
    array.append(str);
    return array;
}

bool TTucmd::handleData(QString cmd, QString revdata)
{
    QString split = (mDeviceType==1?QString("\x0d\x0a\x0d\x0a"):QString("\r\r\n\r\r\n"));
//    qout << mDevIndex <<"cmd >>> " << cmd << revdata;
    QRegExp rx("ip addr add(.+)dev FE0");
    if(cmd.contains(rx)){//设置Ip
        if (revdata.isEmpty()||revdata.trimmed().contains("IP address exists")) {
            mRevOKFlag=true;
            emit RespondsetTTUIP(mDevIndex,true);
        } else {
            qout << g_C2Q("设置ip异常:") << revdata;
            emit RespondsetTTUIP(mDevIndex,false);
        }
    }
    else if(cmd.contains(QRegExp("ip addr del (.+) dev FE0"))){//删除Ip
        if (revdata.isEmpty()||revdata.trimmed().contains("IP address not exists")) {
            mRevOKFlag=true;
            mOldIpList.removeAt(0);
        } else {//会存在一些异常,打印体现
            qout << g_C2Q("设置ip异常:") << revdata;
        }
    }

    else if (cmd.contains("version -b")) {//查询硬件版本号
        QString version = revdata.trimmed();
        emit RespondgetVersion(mDevIndex,version);
    }

    else if (cmd.contains("devctl -H")) {//查询scu硬件版本号
        QString version = revdata.trimmed();
        emit RespondgetScuVersion(mDevIndex,version);
    }

    else if (cmd.contains("cat /proc/cpuinfo")) {//查看cpu信息,未按容器分
        QStringList list= revdata.trimmed().split("\n");
        QMap<QString,QString> infomap;
        infomap.clear();

        for(int i=0; i<list.length(); ++i){
            QString info = list[i].trimmed();
            if(info.trimmed().isEmpty())//去除分割时的空字符串
                continue;
            QStringList kvlist = info.split(":");
            if(kvlist.length()!=2){

                qout << "cpuinfo "<< i+1 << "result is error:" << info;
                continue;
                //return false;
            }

            infomap.insert(kvlist[0].trimmed(),kvlist[1].trimmed());
        }
        emit(this->RespondgetCPUInfo(mDevIndex,infomap));
    }
    else if (cmd.contains("ping 8.8.8.8")) {//查看上线
        if (revdata.trimmed().contains("Network is reachable"),Qt::CaseInsensitive) {
            emit RespondcheckOnline(mDevIndex,true);
        } else {
            emit RespondcheckOnline(mDevIndex,false);
        }
    }
    else if (cmd.contains("top -b -n 1 -d 10")) {//查看上线sudo -s
        if (revdata.trimmed().contains("Mem",Qt::CaseInsensitive)||revdata.trimmed().contains("cpu",Qt::CaseInsensitive)) {
            emit RespondQueryProcess(this->mDevIndex,true);
        } else {
            emit RespondQueryProcess(this->mDevIndex,false);
        }
    }
    else if (cmd.contains("container status")||cmd.contains("container: It will take some time to get status, please wait a moment.")) {//查看容器信息
        //暂时不确定，先按\0d\0d\n\0d\0d\n分解两个容器之间的东西
        QStringList lxclist = revdata.split(split);//找不到则直接返回整个string
        QList<_ContainerInfo> contlist;
        contlist.clear();
        for(int i=0; i<lxclist.length(); ++i){
            QStringList list= lxclist[i].trimmed().split("\r\n");
            _ContainerInfo info;

            for(int j=0; j<list.length(); ++j){
                QString  continfo = list.at(j);
                if(continfo.trimmed().isEmpty())//去除分割时的空字符串
                    continue;
                QStringList kvlist = continfo.split(":");
                if(kvlist.length()!=2){
                    qout << "continfo result is error:" << continfo;
                    continue;
                }

                QString key = kvlist[0].trimmed();
                QString value = kvlist[1].trimmed();
                if(key.contains("container index",Qt::CaseInsensitive)){
                    info.index = value.toInt();
                }
                else if(key.contains("container name",Qt::CaseInsensitive)){
                    info.name = value;
                }
                else if(key.contains("container version",Qt::CaseInsensitive)){
                    info.version = value;
                }
                else if(key.contains("container patch version",Qt::CaseInsensitive)){
                    info.pathcVersion = value;
                }
                else if(key.contains("container status",Qt::CaseInsensitive)){
                    info.status = value;
                }
                else if(key.contains("container ip",Qt::CaseInsensitive)){
                    info.ip = value;
                }
                else if(key.contains("container cpu-usage",Qt::CaseInsensitive)){
                    info.cpUsage = value.remove("%").toInt();
                }
                else if(key.contains("container max mem",Qt::CaseInsensitive)){
                    info.maxMem = value;
                }
                else if(key.contains("container mem-usage",Qt::CaseInsensitive)){
                    info.memUsage = value.remove("%").toInt();
                }
                else if(key.contains("container disk-size",Qt::CaseInsensitive)){
                    info.diskSize = value;
                }
                else if(key.contains("container disk-usage",Qt::CaseInsensitive)){
                    info.diskUsage = value.remove("%").toInt();
                }
            }
            contlist.append(info);
        }
        emit(this->RespondgetContainerSts(mDevIndex,contlist));
    }
    else if (cmd.contains("container stop")) {//停止容器
        QString name = cmd.trimmed().split(" ").last().trimmed();//容器名
        if (revdata.contains("stop container "+name+" success")){
            emit RespondstopContainer(mDevIndex,name,true);
        } else {
            emit RespondstopContainer(mDevIndex,name,false);
        }
    }
    else if (cmd.contains("container start")) {//启动容器
        QString name = cmd.trimmed().split(" ").last();//容器名

        if (revdata.contains("start container "+name+" success")) {
            emit RespondstartContainer(mDevIndex,name,true);
        } else {
            emit RespondstartContainer(mDevIndex,name,false);
        }
    }
    else if(cmd.contains(QRegExp("appm -I -c (.+) -n (.+)"))){
        int index1 =  revdata.indexOf("App version")+1;
        int index2 =  revdata.indexOf("App hash")-revdata.indexOf("App version")-1;
        QString content = revdata.mid(index1,index2);
        QString value;
        if(content.split(":").count()==2){
            QString tmp = content.split(":").at(1);
            value = tmp.remove(QRegExp("\r|\n|\\s"));
        }
        emit ResondAppVersion(mDevIndex,value);
    }
    else if (cmd.contains("appm -I -c")) {//查看容器App信息
        QStringList applist = revdata.trimmed().split(split);//找不到则直接返回整个string
        QList<_AppInfo> appinfolist;
        appinfolist.clear();

        for(int i=1; i<applist.length(); ++i){//第一行是统计的，不算

            QStringList list= applist[i].trimmed().split("\r\n");
            _AppInfo appinfo;

            for(int j=0; j<list.length(); ++j){
                QString  info = list.at(j);
                if(info.trimmed().isEmpty())//去除分割时的空字符串
                    continue;
                QStringList kvlist = info.split(":");
                if(kvlist.length()<2){//不用!=2是因为start time
                    qout << "continfo result is error:" << info;
                    return false;
                }

                QString key = kvlist[0].trimmed();
                QString value = kvlist[1].trimmed();

                if(key.contains("App index")){
                    appinfo.index = value.toInt();
                }
                else if(key.contains("App name")){
                    appinfo.name = value;
                }
                else if(key.contains("App version")){
                    appinfo.version = value;
                }
                else if(key.contains("App hash",Qt::CaseInsensitive)){
                    appinfo.hash = value;
                }
                else if(key.contains("App was verified",Qt::CaseInsensitive)){
                    appinfo.isVerified = value.contains("Yes")?true:false;
                }
                else if(key.contains("Service index",Qt::CaseInsensitive)){
                    appinfo.serviceIndex = value.toInt();
                }
                else if(key.contains("Service name",Qt::CaseInsensitive)){
                    appinfo.serviceName = value;
                }
                else if(key.contains("Service enable",Qt::CaseInsensitive)){
                    appinfo.serviceEnable = value.contains("yes")?true:false;
                }
                else if(key.contains("Service status",Qt::CaseInsensitive)){
                    appinfo.servicStatus = value;
                }
                else if(key.contains("Cpu threshold",Qt::CaseInsensitive)){
                    appinfo.cpuThreshold = value.remove("%").toFloat();
                }
                else if(key.contains("Cpu usage",Qt::CaseInsensitive)){
                    appinfo.cpUsage = value.remove("%").toFloat();
                }
                else if(key.contains("Mem threshold",Qt::CaseInsensitive)){
                    appinfo.memThreshold = value;
                }
                else if(key.contains("Mem usage",Qt::CaseInsensitive)){
                    appinfo.memUsage = value;
                }
                else if(key.contains("Start time",Qt::CaseInsensitive)){
                    appinfo.startTime = "";
                    for(int m=1; m<kvlist.length(); ++m){//时间格式为2019-10-31 23:20:03 与split(:)冲突
                         appinfo.startTime+=kvlist.value(m);
                         if(m!=kvlist.length()-1){
                             appinfo.startTime+=":";
                         }
                    }
                }
            }
            appinfolist.append(appinfo);
        }
        emit(this->RespondgetAppInfo(mDevIndex,appinfolist));
    }
    else if (cmd.contains("appm -S -c")) {//暂停app
        QString tmp = cmd.trimmed().split("-c").last();//容器名+ -n +app名
        QStringList list = tmp.trimmed().split(" -n ");
        if(list.length()!=2){
            qout << "stop app result is error:" << tmp;
            return false;
        }
        QString contname = list[0].trimmed();
        QString appname = list[1].trimmed();

        if (revdata.contains("success") || revdata.contains("sucess")) {
            emit RespondstopApp(mDevIndex,contname,appname,true);
        } else {
            qout << g_C2Q("停止容器:%1的app:%2异常:").arg(contname).arg(appname) << revdata;
            emit RespondstopApp(mDevIndex,contname,appname,false);
        }
    }
    else if (cmd.contains("appm -s -c")) {//启动app
        QString tmp = cmd.trimmed().split("-c").last();//容器名+ -n +app名
        QStringList list = tmp.trimmed().split(" -n ");
        if(list.length()!=2){
            qout << "start app result is error:" << tmp;
            return false;
        }
        QString contname = list[0].trimmed();
        QString appname = list[1].trimmed();

        if (revdata.contains("success") || revdata.contains("sucess")) {
            emit RespondstartApp(mDevIndex,contname,appname,true);
        } else {
            qout << g_C2Q("启动容器:%1的app:%2异常:").arg(contname).arg(appname) << revdata;
            emit RespondstartApp(mDevIndex,contname,appname,false);
        }
    }
    else if(cmd.contains(QRegExp("curl (.+) -o (.+)"))) {//拷贝
        emit RespondcopyApp(mDevIndex,"1","1",true);
    }
    else if(cmd.contains(QRegExp("appm -i -c(.+) -f (.+)"))) {//安装app
        QString info = cmd.remove("appm -i -c ").trimmed();
        QStringList tmplist = info.split(" -f ");

        if (revdata.isEmpty()) {
            emit RespondinstallApp(mDevIndex,tmplist[0],tmplist[1],true);
        } else {//会存在一些异常,打印体现
            qout << g_C2Q("容器%1安装app %2异常:").arg(tmplist[0]).arg(tmplist[1]) << revdata;
            emit RespondinstallApp(mDevIndex,tmplist[0],tmplist[1],false);
        }
    }
    else if(cmd.contains(QRegExp("appm -u -c (.+) -n (.+)"))) {//卸载app
        QString info = cmd.remove("appm -u -c ").trimmed();
        QStringList tmplist = info.split(" -n ");

        if (revdata.isEmpty()) {
            emit ResponduninstallApp(mDevIndex,tmplist[0],tmplist[1],true);
        } else {//会存在一些异常,打印体现
            qout << g_C2Q("容器%1卸载app %2异常:").arg(tmplist[0]).arg(tmplist[1]) << revdata;
            emit ResponduninstallApp(mDevIndex,tmplist[0],tmplist[1],false);
        }
    }
    else if(cmd.contains("ip addr show")){
        QStringList tmplist = revdata.trimmed().split("\r\n");  //按行分解
        mOldIpList.clear();

        for(int i=0; i<tmplist.length(); ++i){
            QString tmpstr = tmplist.at(i);
            if(tmpstr.contains(QRegExp("inet (.+) brd (.+) scope global FE0"))){    //匹配FE0的ip
                tmpstr.remove("inet");
                tmpstr.remove(QRegExp("brd (.+) scope global FE0"));        //删除非ip部分
                if(!tmpstr.trimmed().isEmpty())         //非空
                    mOldIpList.append(tmpstr.trimmed());                        //存储
            }
        }

        mRevOKFlag=true;
    }
    else if(cmd.contains("nft list tables")){      //获取规则表,格式：table ip dnat1
                                              //table ip dnat2
        mRevOKFlag=true;
        mRoleTable.clear();
        mRoleIndex=0;
        QStringList tmplist = revdata.trimmed().split("\n");
        for(int i=0; i<tmplist.length(); ++i){
            QString tmpstr = tmplist.value(i);
            tmpstr.remove("table ip");
            mRoleTable.append(tmpstr.trimmed());
        }
    }
    else if(cmd.contains("nft delete table")){      //删除规则表dnat1
        if(revdata.trimmed().isEmpty()||revdata.contains("Could not process rule: No such file or directory")){
            mRevOKFlag=true;
        }
        else{       //打印
            qout << "result of " << cmd.trimmed() << " : " << revdata.trimmed();
        }
    }
    else if(cmd.contains("nft add table dnat1")){      //添加规则表dnat1
        if(revdata.trimmed().isEmpty()){
            mRevOKFlag=true;
        }
        else{       //打印
            qout << "result of " << cmd.trimmed() << " : " << revdata.trimmed();
        }
    }
    else if(cmd.contains(("nft add chain dnat1"))){      //添加规则表dnat1
        if(revdata.trimmed().isEmpty()){
            mRevOKFlag=true;
        }
        else{       //打印
            qout << "result of " << cmd.trimmed() << " : " << revdata.trimmed();
        }
    }
    else if(cmd.contains("nft add rule dnat1 prerouting ip daddr")){      //添加规则表dnat1
        if(revdata.trimmed().isEmpty()){
            mRevOKFlag=true;
        }
        else{       //打印
            qout << "result of " << cmd.trimmed() << " : " << revdata.trimmed();
        }
    }
    else if(cmd.contains("bd -G_B -t") || (cmd.isEmpty() && revdata.contains("Update time success!"))){  //GPS对时 cmd.contains("bd -G -t")||cmd.contains("bd -B -t")
        if(revdata.contains("Update time success!")){
            emit RespondTime(mDevIndex,true);
        }
        else{
            emit RespondTime(mDevIndex,false);
        }
    }
    else if(cmd.contains("bd -G_B -l") || (cmd.isEmpty() && revdata.contains("Get location success!"))){  //GPS定位 cmd.contains("bd -G -l")||cmd.contains("bd -B -l")
        QStringList tmplist = revdata.trimmed().split("\r\n");  //按行分解
        QString e,n,h;
        for(int i=0; i<tmplist.length(); ++i){

            QString tmpstr = tmplist.at(i);
            QStringList strlist = tmpstr.trimmed().split(":");
            if(tmpstr.contains("Longitude")){
                if(strlist.length()>=2){
                    e = strlist.at(1);
                }
            }
            else if(tmpstr.contains("Latitude")){
                if(strlist.length()>=2){
                    n = strlist.at(1);
                }
            }
            else if(tmpstr.contains("High")){
                if(strlist.length()>=2){
                    h = strlist.at(1);
                }
            }
        }
        emit RespondPos(mDevIndex,e,n,h);
    }
    else if(cmd.contains("devctl -e")){
        QStringList list = revdata.split(":");
        if(list.length()==2)
        {
            emit RespondESN(mDevIndex,list.at(1).trimmed());
        }
        else
            emit RespondESN(mDevIndex,QString());
    }
    else if(cmd.contains("version -d")){
        QStringList list = revdata.split("patch version:");
        if(list.length()==2)
        {
            emit RespondESN(mDevIndex,list.at(1));
        }
        else
            emit RespondESN(mDevIndex,QString());
    }
    else{
        RevData.clear();
        return false;
    }
    return true;
}

bool TTucmd::login(QString str)
{
    if(str.contains(QRegExp(".* login:"))){
        emit RevCmdMsg(mDevIndex,str);
        RevData.clear();
        writeUserName();
        return true;
    }
    else if(str.contains("Password:")||str.contains("[sudo] password for sysadm:")){
        emit RevCmdMsg(mDevIndex,str);
        RevData.clear();
        writePassword();
        return true;
    }
    return false;
}

void TTucmd::QueryRuleTable()
{
    QString cmd = QString("nft list tables");
    if(!sendCmd(cmd)){
        qout << "QueryRuleTable error!";
    }
}

void TTucmd::DelRuleTable(QString tname)
{
    QString cmd = QString("nft delete table ")+tname;
    if(!sendCmd(cmd)){
        qout << "DelRuleTable error!";
    }
}

void TTucmd::addRuleTable()
{
    QString cmd = QString("nft add table dnat1");
    if(!sendCmd(cmd)){
        qout << "addRuleTable error!";
    }
}

void TTucmd::addChain(QString cmd)
{
    if(!sendCmd(cmd)){
        qout << "addChain error!";
    }
}

void TTucmd::addNetMapping()
{
    QString cmd = "nft add rule dnat1 prerouting ip daddr "+mNetMapIp1+" tcp dport 2404 iif FE0 dnat "+mNetMapIp2;
    if(!sendCmd(cmd)){
        qout << "addNetMapping error!";
    }
}

void TTucmd::filterRevMsg(QString &msg)
{
    msg.replace(QRegExp("\033(\\[).;.(.?)m"), "");//      .(\\[).;.(.?)m 或者\x1B(\\[).;.(.?)m
    msg.replace(QRegExp("\033(\\[)0m"), "");
    msg.replace(QRegExp("\033\\[.*r"),"");
    msg.replace(QRegExp("\033\\[."),"");
    msg.replace(("1;32m"),"");
    msg.replace("0;0m","");
    msg.replace("0m","");
    msg.replace("0;1m","");
}

int TTucmd::matchEndText(QString &revstr)
{
    //匹配结束字段
    QRegExp rx("\\[admin@.*\\]\\$");//("1...m");
    QRegExp rx2("sysadm@.*\\$");
    int ret = -1;
    if(mDeviceType==1){
        if(revstr.contains("If you want to exit,please type 'q'"))
            ret = 1;
        else
            ret = rx2.indexIn(revstr);
    }
    else{
        ret = rx.indexIn(revstr);
    }

    if(ret != -1){//成功
        QStringList strlist = revstr.split(mDeviceType==1?rx2:rx);
        if(strlist.length()>1&&!strlist[1].trimmed().isEmpty()){
            RevData.clear();
            RevData.append(strlist[1]);

        }
        else{
            RevData.clear();
        }
        if(strlist.length()>0){
            revstr=strlist[0];
        }
        filterRevMsg(revstr);
    }
    return ret;
}



void TTucmd::readData()
{
    if(linkModel==1){
        RevData.append(mSerial->readAll());
    }
    else{
        RevData.append(m_shell->readAllStandardOutput());
    }
    QString revstr = Hex2Str(RevData);
    //登录
    if(login(revstr)){
        return;
    }
    //重启回复判断
    if(revstr.contains("Info: system is rebooting, please wait...")){
        mRevOKFlag=true;
    }
    else if(revstr.contains("System will reboot! Continue? [y/n]:")){   //重启确认
        mRevOKFlag=true;
    }

    //判断是否在融合终端映射
    if(isFuseTermMap){
        //直接打印，
        filterRevMsg(revstr);
        //清空revdata
        RevData.clear();
        return;
    }

    if(matchEndText(revstr) != -1){//成功
        QString cmd = revstr.left(revstr.indexOf("\n")+1).trimmed();
        revstr.remove(0,revstr.indexOf("\n")+1);//回复时会带操作的命令
        //根据命令进行处理
        if( revstr.isEmpty() )
            return;
        handleData(cmd,revstr.trimmed());
        emit RevCmdMsg(mDevIndex,revstr);
    }
    if(RevData.length()>512*1024){
        qWarning() << g_C2Q("设备%1数据溢出").arg(mDevIndex) << __FILEW__ << __LINE__;
        RevData.clear();
    }
}

void TTucmd::errorOccurred(QAbstractSocket::SocketError error)
{
    if(error==0){
        return;//no error
    }
}

void TTucmd::HandleTimeout()
{
    mpTimer->stop();
    if(mRevOKFlag)
    {
        mRevOKFlag=false;
        if(miSteps==mTotalSteps){     //判断结果
            emit(this->RespondNetMap(mDevIndex,"set net mapping OK",true));
            isFuseTermMap=false;
        }
        else{
            mapInterAcess();
        }
    }
    else
    {
        emit(this->RespondNetMap(mDevIndex,QString("step %1 time out").arg(miSteps-1),false));
        miSteps=0;
        isFuseTermMap=false;
    }

}

void TTucmd::initParams()
{
    m_argParameters.setPort(mPortArgs.port);
    m_argParameters.setUserName(mUser);
    m_argParameters.setPassword(mKey);
    m_argParameters.setHost(mPortArgs.IP);
    m_argParameters.timeout = 10;
    m_argParameters.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypeTryAllPasswordBasedMethods; //密码方式连接

    m_bConnected = false;
    m_pSshSocket = nullptr;
}

void TTucmd::slotConnected()
{
    m_bConnected = true;
    m_shell = m_pSshSocket->createRemoteShell();
    connect(m_shell.data(), SIGNAL(started()), SLOT(slotShellStart()));
    connect(m_shell.data(), SIGNAL(readyReadStandardOutput()), SLOT(readData()));
    connect(m_shell.data(), SIGNAL(readyReadStandardError()), SLOT(slotShellError()));
    m_shell.data()->start();
    emit SshStateChanged(mDevIndex,m_bConnected);
}

void TTucmd::slotSshConnectError(QSsh::SshError sshError)
{
    if(sshError == QSsh::SshNoError)
        return;
    m_bConnected = false;
    switch(sshError){
    case QSsh::SshNoError:
        qDebug()<<"slotSshConnectError SshNoError"<<getIpPort();
        break;
    case QSsh::SshSocketError:
        qDebug()<<"slotSshConnectError SshSocketError"<<getIpPort(); //拔掉网线是这种错误
        break;
    case QSsh::SshTimeoutError:
        qDebug()<<"slotSshConnectError SshTimeoutError"<<getIpPort();
        break;
    case QSsh::SshProtocolError:
        qDebug()<<"slotSshConnectError SshProtocolError"<<getIpPort();
        break;
    case QSsh::SshHostKeyError:
        qDebug()<<"slotSshConnectError SshHostKeyError"<<getIpPort();
        break;
    case QSsh::SshKeyFileError:
        qDebug()<<"slotSshConnectError SshKeyFileError"<<getIpPort();
        break;
    case QSsh::SshAuthenticationError:
        qDebug()<<"slotSshConnectError SshAuthenticationError"<<getIpPort();
        break;
    case QSsh::SshClosedByServerError:
        qDebug()<<"slotSshConnectError SshClosedByServerError"<<getIpPort();
        break;
    case QSsh::SshInternalError:
        qDebug()<<"slotSshConnectError SshInternalError"<<getIpPort();
        break;
    default:
        break;
    }
    emit SshStateChanged(mDevIndex,false);
}

void TTucmd::slotShellStart()
{
    m_bConnected = true;
    qDebug()<<QString::fromLocal8Bit("CConnectionForSshClient::slotShellStart Shell已连接:")<<getIpPort();
}

void TTucmd::slotShellError()
{
    qDebug()<<QString::fromLocal8Bit("CConnectionForSshClient::slotShellError Shell发生错误:")<<getIpPort();
}
